// Cross-platform socket wrapper
// Copyright 2004 (C) Ralph Thomas

#ifndef SOCKET_H
#define SOCKET_H

#include <util/string.h>

namespace util {
	//
	/// The socket class provides a simple interface for using a socket
	/// as a client. In the future it could be extended to provide server
	/// functionality also.
	//
	class socket {
	  public:
		//
		/// These are the possible errors which we could have when
		/// dealing with sockets. Most of the functions will have
		/// and "errorCode" return type, the comment should say which
		/// the possible set of return values for each function.
		//
		enum errorCode {
			kOk = 0,	///< The operation completed OK
			kTimeout = -1,	///< The operation timed out and failed
			kDisconnected = -2,	///< The other end disconnected
			kFailure = -3	///< The operation failed in a generic way
		};

		//
		// socket* fromHostnameAndPort( util::string hostname, int port )
		//
		/// Return a new socket object that is connected to
		/// hostname:port. If the hostname cannot be resolved to an
		/// IP address, or that machine refuses the connection or fails
		/// to respond to the connection request then NULL is returned.
		///
		/// \param	hostname	the name of the machine to connect to.
		/// \param	port		the port on that machine to connect to.
		/// \return	a new connected socket object, or NULL.
		//
		static socket* fromHostnameAndPort( util::string hostname, int port );

		//
		// virtual ~socket()
		//
		/// Disconnect from the remote host and free associated memory.
		//
		virtual ~socket();

		//
		// virtual errorCode send( util::string message )
		//
		/// Send a message to the machine connected at the other end
		/// of the socket.
		///
		/// \param	message	the message to send to the other
		///			machine
		/// \return	the errorCode can be any of the following:
		///		 - kOk
		///		 - kTimeout
		///		 - kDisconnected
		//
		virtual errorCode send( util::string message ) = 0;

		//
		// virtual errorCode recieve( util::string& message, int nbytes )
		//
		/// Read at most nbytes bytes into the given string
		/// reference. If no data is available, then nothing is put
		/// into the string reference and kOk is returned.
		///
		/// \param	message	the string reference to put recieved
		///			data
		/// \param	nbytes	the number of bytes to read into the
		///			string reference.
		/// \return	the errorCode can be any of the following:
		///		 - kOk
		///		 - kDisconnected
		//
		virtual errorCode recieve( util::string& message, int nbytes ) = 0;

		//
		// virtual errorCode recieveLine( util::string& message )
		//
		/// Wait until an entire line (terminated by the newline
		/// character) has been recieved and put that into the given
		/// string reference.
		///
		/// \param	message	the string reference to put recieved
		///			data
		/// \return	the errorCode can be any of the following:
		///		 - kOk
		///		 - kTimeout
		///		 - kDisconnected
		//
		virtual errorCode recieveLine( util::string& message ) = 0;

		//
		// bool isDataAvailable( int timeout )
		//
		/// Check to see if there is any data available on the socket,
		/// if there is some data which could be read then return true,
		/// if there is no data to be read then false is returned.
		///
		/// \param	timeout	number of seconds to keep checking for,
		///			0 means return right away.
		///
		/// \return	true	if there is data which could be read
		///		false	if there is no data to be read
		//
		virtual bool isDataAvailable( int timeout ) = 0;
		//
		// bool startTLS()
		//
		/// Start a TLS encrypted session with the server. This is
		/// often done in the middle of an unencrypted session, for
		/// example, IMAP's STARTTLS command.
		///
		/// \return	true if the TLS handshake was successful,
		///		false otherwise.
		//
		virtual bool startTLS() = 0;
	};
};

#endif

